<?php
/*
    phpManager3000 v0.1 
	管理控制台3000 v0.1
	
    Copyright (c) 2012, greatqn@163.com
    The phpManager3000 project is under MIT license.
    
    follow me http://weibo.com/greatqn
*/
define(LF, "\r\n"); 
define(INIFILE, "config.ini"); 
date_default_timezone_set('PRC');

$cmd = "help";
if(count($argv)>1){
	$cmd = $argv[1];
}
$cmdHost = new $cmd();
$cmdHost->run($argv);


class Command_Base{
	function run($argv){
		var_dump($argv);
		$arr = $this->get_argv($argv);
		var_dump($arr);
	}
	//分解参数 -file="xxx"
	function get_argv($argv){
		$result = array();
		foreach($argv as $str){
			if(strpos($str,"-")==0 && strpos($str,"=")>0){
				$result[substr($str,1,strpos($str,"=")-1)]
				 = substr($str,strpos($str,"=")+1);
			}			
		}
		return $result;
	}
}

class log extends Command_Base{
	function run($argv){
		$ar = new LogAnalys();
		$arr = $this->get_argv($argv);
		$ar->analys($arr);
	}
}

class help extends Command_Base{
	function run($argv){
		$msg = array();
		$msg[] = "help:";
		$msg[] = "php.exe manager.php [cmd] [arg]";
		$msg[] = "cmd:";
		$msg[] = "   main           command line menu";
		$msg[] = "   log            log Analy";
		$msg[] = "   test           unit test";
		$msg[] = "-------------------------------";
		$msg[] = '"D:\xampp\php\php.exe" ./manager.php log -file="C:/Documents and Settings/dell/桌面/tt/2012-09-17-zhirong-access-9c.log" -filter=eq -where=IP=175.43.195.123';
		$msg[] = '-outfile|-outfile_pix,-showinfo=1|0,-filter=eq|like|between,where=key=value -wherenot=1';
		msg_log($msg);
	}
}


/**
 * 测试类
 */
class test extends Command_Base{

	function run($argv){
		//$this->testConfig();
		//$this->testCmd();
		$this->testLog();
		//$this->testLogAnalyReport();
	}

	function testConfig(){
		$config = Config::getInstance();
		$config = Config::getInstance();
		echo $config->get("dd");
		echo $config->get("sys_os");
		$config->set("dd","ff");
		echo $config->getBasePath();
	}
	
	function testCmd(){
		//$rs = run_cmd("ant -f E:\ancun.com\build\build_log.xml phpbuild");
		
		$config = Config::getInstance();	
		//$dt = $config->get("log_get_date");
		$dt = date('Y-m-d');
		$today = date('Ymd',strtotime($dt));
		$oldday = date('Ymd',strtotime($dt)-10*24*60*60);//时间加减
		var_dump($dt);
		var_dump($today);
		var_dump($oldday);

		$rs = run_cmd("ant -f E:\project\build\build.xml -Dgfile=$today.zip ftp-get");
		msg_log($rs["logs"]);
		$rs = run_cmd("ant -f E:\project\build\build.xml -Dgfile=$oldday.zip ftp-del");
		msg_log($rs["logs"]);
		
	}
	function testLog(){
		T::BT(1);
		$log = new LogAnalys();
		$log->test_regex();
		//$log->analys(null);
		T::Mem();
		echo T::ET(1)."s";
	}
	function testLogAnalyReport(){
		$ar = new LogAnalyReport();
		$ar->outfile = "C:/Documents and Settings/dell/桌面/tt/XX-project-access-9c_out.log";
		var_dump($ar);
	}
}
/**
 * 菜单类
 */
class menu{
	var $cmdarr = array(
		"d"    =>"httpdownload",
		"uz"   =>"unzip",		
		"up"   =>"uploadwebroot",		
		"up1"  =>"uploadwebroot_1",		
		"b"    =>"backup",		
		"b1"   =>"backup2webroot_1",	
		"c"    =>"change_root",	
		"init" =>"init_path",
		"s"    =>"showconfig",
		"set"  =>"setconfig",
		"bmy"  =>"backupmysql",
		"x"    =>"exit",
	);

	function run($argv){
		$key = "s";
		while($key != "x")
		{
			$this->main($key);
			$this->showmenu();
		    fwrite(STDOUT, "\r\nPlease input your select:");
		    $key = trim(fgets(STDIN));
		}
		echo "bye";
	}
	function showmenu(){
		echo "============================================================\r\n";
		foreach($this->cmdarr as $key=>$value){
			echo "\t$key\t:$value\r\n";
		}
		echo "============================================================\r\n";
	}
	
	function main($key){
		$cmd = $this->cmdarr[$key];
		//echo $cmd;
		$this->$cmd();
	}
	function downloadf(){
		global $httpfile,$root,$uploadfolder,$webroot,$backup,$upfilename;
		echo "$httpfile:";
		$upfilename = trim(fgets(STDIN));
		download($httpfile.$upfilename,$uploadfolder);
	}

	function unzipf(){
		global $httpfile,$root,$uploadfolder,$webroot,$backup,$upfilename,$configpath;
		if(empty($upfilename)) {
			echo "Error:upfile is not exists\r\n";
			return -1;
		}
	
		$f = explode(".",$upfilename);
		$f = $f[0];
		//echo $f;
		unzip($uploadfolder.$upfilename,$uploadfolder.$f."\\");
		pause();
	
		xcopy($configpath,$uploadfolder.$f."\\",1);
		echo "copy config ";
	}
	
	function upload(){
		global $httpfile,$root,$uploadfolder,$webroot,$backup,$upfilename;
		$f = explode(".",$upfilename);
		$f = $f[0];
		xcopy($uploadfolder.$f."\\",$webroot,1);
		pause();
	}
	
	function upload2(){
		global $httpfile,$root,$uploadfolder,$webroot,$backup,$upfilename;
		$newstr = checkwebroot1($webroot);
		$f = explode(".",$upfilename);
		$f = $f[0];
		xcopy($uploadfolder.$f."\\",$newstr,1);
		pause();
	}
	
	function changefolderf(){
		global $webroot;
	
		$len=strlen($webroot); 
		$newstr=substr($webroot,0,$len-1);  
	
		changefolder($newstr,$newstr."_1");
	}
	function showconfig(){
		$config = Config::getInstance();
		var_dump($config->config);
	}
	
	function setconfig(){
		$config = Config::getInstance();
		fwrite(STDOUT, "\r\ninput key=value:");
		$key = trim(fgets(STDIN));
		$arr = explode("=",$key);
		if(count($arr) == 1){
			echo "input error";
			return;
		}
		//var_dump($arr);
		$config->set($arr[0],$arr[1]);
	}

	function backupwebroot(){
		echo "begin backup\r\n";
		global $httpfile,$root,$uploadfolder,$webroot,$backup;
		$bakpath = $backup."web\\";
		mkdir_f($bakpath);
		$bakpath = $bakpath.date("YmdH");
		xcopy($webroot,$bakpath,1);
		echo "backup end to path:$bakpath\r\n";
		pause();
	}
	
	function backupwebroot1(){
		echo "begin backup to _1\r\n";
		global $httpfile,$root,$uploadfolder,$webroot,$backup;
		$newstr = checkwebroot1($webroot);
		xcopy($webroot,$newstr,1);
		echo "backup end to path:$newstr\r\n";
		pause();
	}
	
	function checkwebroot1($webroot){
		$len=strlen($webroot); 
		$newstr=substr($webroot,0,$len-1)."_1\\"; 
		$rs = del_dir($newstr);
		//var_dump($rs);
		mkdir_f($newstr);
		return $newstr;
	}
	
	function backupmysql(){
		echo "begin backup mysql\r\n";
		global $httpfile,$root,$uploadfolder,$webroot,$backup;
		$bakpath = $backup."db\\";
		mkdir_f($bakpath);
		$sqlpath = $bakpath."data.sql";
		$rarpath = $bakpath.date("YmdH").".rar";
		mysql_backup($sqlpath);
		zip_f($rarpath,$sqlpath);
		unlink($sqlpath);
		echo "backup end to path:$sqlpath\r\n";
		pause();
	
	}
	
	function pause(){
		echo "any key to continue...";
		fgets(STDIN);
	}
	
	function initpath(){
		global $httpfile,$root,$uploadfolder,$configpath,$backup;
	
		echo "init path $root config\r\n";
		mkdir_f($root."config");
		mkdir_f($root."webroot");
		mkdir_f($root."logs");
	
		echo "init path $uploadfolder\r\n";
		mkdir_f($uploadfolder);
		echo "init path $backup\r\n";
		mkdir_f($backup);
		echo "init path $configpath\r\n";
		mkdir_f($configpath);
		echo "init path end\r\n";
		
	}
	/**
	 * $dt 日期 2010-09-10 的格式
	 * 下载当前的日志文件
	 * 删除10天前的日志文件
	 */
	function get_log_from_ftp($dt){
		$today = date('Ymd',strtotime($dt));
		$oldday = date('Ymd',strtotime($dt)-10*24*60*60);
		var_dump($dt);
		var_dump($today);
		var_dump($oldday);

		$rs = run_cmd("ant -f E:\project\build\build.xml -Dgfile=$today.zip ftp-get");
		msg_log($rs["logs"]);
		$rs = run_cmd("ant -f E:\project\build\build.xml -Dgfile=$oldday.zip ftp-del");
		msg_log($rs["logs"]);
	}

}
/**
* 日志分析
*/
class LogAnalys{
	//1.IP 2.时间 3.请求 4.状态 5.大小 6.来源 7.客户端 8.耗时 9.进程
	var $regex = '/^([\d\.]+) .+ .+ \[(.+)\] "(((?!").)+)" (\d*) (.*) (.*) "(((?!").)*)" (\d*) (\d*).*$/i';
	//    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %T %P" combined
	
	
	public function test_regex(){
		$str = '208.115.113.90 - - [11/Sep/2012:05:23:55 +0800] "GET /file/file/guhua HTTP/1.1" 302 - "-" "Mozilla/5.0 (compatible; Ezooms/1.0; ezooms.bot@gmail.com)"';
		$rs  = $this->get_matches($str);
		var_dump($rs);
		echo $rs==false?"ERROR":"Sccess";
		echo LF;
		$str = '60.195.252.106 - - [11/Sep/2012:02:06:03 +0800] "GET /server-status HTTP/1.1" 200 6097 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JianKongBao Monitor 1.1)"';
		$rs  = $this->get_matches($str);
		var_dump($rs);
		echo $rs==false?"ERROR":"Sccess";
		echo LF;
		$str = '14.223.97.219 - - [15/Sep/2012:00:23:39 +0800] "GET /favicon.ico HTTP/1.1" 200 1934 "-" "" 0 10744';
		$rs  = $this->get_matches($str);
		var_dump($rs);
		echo $rs==false?"ERROR":"Sccess";
		echo LF;
		
		$info = $this->get_loginfo($rs);
		var_dump($info);
		
		$ar = new LogAnalyReport();
		
		$outfile = "C:/Documents and Settings/dell/桌面/tt/XX-access-9c_out.log";
		$outfile = iconv("UTF-8", "GBK", $outfile);
		$ar->outfile = $outfile;
		$ar->add($info);
		$ar->report();
		
		return;
	}

	public function get_matches($str){
		$matches = array();
		$reg = $this->regex;
		
		if(preg_match($reg, $str, $matches)){
		    return $matches;
		}
		return false;
	}
	
	public function get_loginfo($arr){
		$rs = array();
		$rs["IP"] = $arr[1];
		$rs["TIME"] = strtotime($arr[2]);
		$url = explode(' ', $arr[3]); 
		$rs["URL"] = $url[1];
		$rs["METHOD"] = $url[0];
		$rs["HTTP"] = $url[2];
		$rs["REFURL"] = $arr[7];
		$rs["STATE"] = $arr[5];
		$rs["USEMEM"] = $arr[6];
		$rs["USETIME"] = $arr[10];
		$rs["PID"] = $arr[11];
		$rs["AGENT"] = $arr[8];
		$rs["LOG"] = rtrim($arr[0]);
		return $rs;
	}
	/**
	 * 主分析代码
	 */
	public function analys($argv){
		
		var_dump($argv);
		$file = $argv["file"];
		//$outfile = $argv[1];
		//$file = "C:/Documents and Settings/dell/桌面/tt/2012-09-16-zhirong-access-9c.log";
		//$file = iconv("UTF-8", "GBK", $file);

		$f1 = new LogAnalyFilter($argv);

		$fp = fopen($file, "r");
		while (!feof($fp))
		{
			//echo ".";
		    $bruce=fgets($fp);
		    if(empty($bruce)) continue;
		    
		    $rs = $this->get_matches($bruce);
		    if($rs==false){
		    	$arr[] = $bruce;
		    }else{
		    	$info = $this->get_loginfo($rs);
				$f1->scan($info);
		    }
		}
	
		fclose($fp);
		$f1->report();

		$outfile = str_replace(".log","_mis.log",$file);
		save_file($outfile,$arr);
		
		msg_log("--end");
		msg_log("$file is analy");
	}
}

/**
 * 分析类
 */
class LogAnalyFilter{
	var $workAnalyReport = null;
	var $workAnalyFilter = null;
	function __construct($argv){
		$def_config = array(
			"outfile" => "",
			"outfile_pix" => "anl",
			"showinfo" => 1,
			"filter" => "",
			"where" => "",
			"wherenot" => 0,
		);
		$config = array_merge($def_config,$argv);
		$file = $argv["file"];
		//组装report		
		$report = new LogAnalyReport();
		$outfile = $config["outfile"];
		if(empty($outfile)){
			$outfile = str_replace(".log","_".$config["outfile_pix"].".log",$file);
		}
		$report->outfile = $outfile;
		$report->showinfo = $config["showinfo"];
		$this->workAnalyReport = $report;
		//组装filter
		if(!empty($config["filter"])){
			$filter = $this->buildfilter($config);
			$this->workAnalyFilter = $filter;
		}
	}
	
	public function scan($info){
		if($this->workAnalyFilter != null){
			if($this->workAnalyFilter->scan($info) == false){
				return false;
			}
		}
		$continue = true;
//		if($this->nextAnalyItem != null){
//			$continue = $this->nextAnalyItem->scan($info);
//		}
		if($continue){
			$this->workAnalyReport->add($info);
		}
		return $continue;
	}
	public function report(){
		$this->workAnalyReport->report();
	}
	//-filter=eq|like|between
	public function buildfilter($config){
		$name = $config["filter"];
		$where = $config["where"];
		$wherenot = $config["wherenot"];
		$result = null;
		switch($name){
			case 'eq':
			$result = new LogEqFilter($where);
			break;
			case 'like':
			$result = new LogLikeFilter($where);
			break;
			case 'between':
			$result = new LogBetweenFilter($where);
			break;
		}
		$result->wherenot = $wherenot;
		return $result;
	}
}

/**
 * 过滤器
 */
class LogEqFilter{
	var $name;
	var $value;
	var $wherenot;
	function __construct($where){
		$k = explode('=', $where); 
		$this->name  = $k[0];
		$this->value = $k[1];
	}
	//运行模型
	public function scan($info){
		$rs = $this->scanwhere($info);
		return $this->wherenot($rs);
	}
	
	public function scanwhere($info){
		return $info[$this->name] == $this->value;
	}
	public function wherenot($rs){
		return $this->wherenot? !$rs : $rs;
	}
}

class LogLikeFilter extends LogEqFilter{ 
	public function scanwhere($info){
		return strpos($info[$this->name],$this->value)>0;
	}
}
//时间之间
class LogBetweenFilter extends LogEqFilter{
	var $begin;
	var $end;
	function __construct($where){
		$k = explode('=', $where); 
		$this->name   = $k[0];
		$this->begin  = strtotime($k[1]);
		$this->end    = strtotime($k[2]);
	}
	public function scanwhere($info){
		echo ($info[$this->name] >= $this->begin) && ($info[$this->name] <= $this->end);
		echo LF;
		return ($info[$this->name] >= $this->begin) && ($info[$this->name] <= $this->end);
	}
}

/**
 * 汇总器
 */
class LogAnalyReport{
	var $use_count;
	var $outfile;
	var $infoarr = array();
	var $showinfo = true;
	
	function __construct()
	{
		$count = array();
		$count["row"] = 0;
		$count["mem"] = 0;
		$count["time"] = 0;
		$count["IP"] = array();
		$count["state"] = array();
		$count["URL"] = array();
		$count["PID"] = array();
		$this->use_count = $count;
	}
	public function add($info){
		//echo  $info["STATE"];
		$count = $this->use_count;
		$count["row"]++;
		$count["mem"] += intval($info["USEMEM"]);
		$count["time"] += doubleval($info["USETIME"]);
		$count["IP"][$info["IP"]] += 1;
		$count["state"][$info["STATE"]] += 1;
		$count["URL"][$info["URL"]] += 1;
		$count["PID"][$info["PID"]] += 1;
		
		if($this->showinfo){
			//echo  $info["LOG"];
			$this->infoarr[] = $info["LOG"].LF;
		}

		$this->use_count = $count;
	}
	public function report(){
		$count = $this->use_count;
		$arr = $this->infoarr;
		
		$arr[] = "==统计信息==".LF;
		$arr[] = "总访问量: ".$count["row"].LF;
		$arr[] = "总流量: ".round($count["mem"]/1024/1024,2)."M".LF;
		$arr[] = "总用时: ".round($count["time"]/1000/1000,2)."S".LF;
		$arr[] = "IP数量：".count($count["IP"]).LF;

		$arr[] = "==状态统计信息==".LF;
		arsort($count["state"]);//排序
		foreach($count["state"] as $k=>$v){
			$arr[] = "$k\t=>$v".LF;
		}		
		$arr[] = "==IP统计信息==".LF;
		arsort($count["IP"]);//排序
		$i = 0;
		foreach($count["IP"] as $k=>$v){
			$arr[] = "$k\t=>$v".LF;
			if($i++ > 9) break;
		}	
		
		$arr[] = "==PID统计信息==".LF;
		arsort($count["PID"]);//排序
		$i = 0;
		foreach($count["PID"] as $k=>$v){
			$arr[] = "$k\t=>$v".LF;
		}	
		
		$arr[] = "==URL统计信息==".LF;
		arsort($count["URL"]);//排序
		$i = 0;
		foreach($count["URL"] as $k=>$v){
			$arr[] = "$k\t=>$v".LF;
			if($i++ > 9) break;
		}
		save_file($this->outfile,$arr);
	}
}
/**
 * 配置类
 */
class Config{
	var $config ;
	var $ini_array;
	static $_instance;
	private function __construct(){
		$this->config = array
		(
			"sys_os"           => 'windows',
			"mng_path_root"    => 'E:\\aaa.com\\',
			"mng_path_upload"  => 'upload\\',
			"mng_path_backup"  => 'backup\\',
			"mng_path_config"  => '{mng_root}config\\default\\',
			"mng_path_logs"    => '{mng_root}logs\\',
			"mng_path_webroot" => '{mng_root}webroot\\',
			"mysql_dump"       => 'D:\\xampp\\mysql\\bin\\mysqldump',
			"tool_winrar"      => 'C:\\Program Files\\WinRAR\\winrar.exe',
			"tool_ant"         => 'ant',
			"tool_svn"         => 'svn',
			"http_file"        => 'http://192.168.0.36/upload/',
			"ftp_file"         => 'http://192.168.0.36/upload/',
		);

		define(FILE_NAME,$this->getBasePath()."\\".INIFILE);

		$this->ini_array = parse_ini_file(FILE_NAME);
		//数组合并
		$this->config = array_merge($this->config, $this->ini_array);         

	}
	/**
	 * 单例。
	 */
	public static function getInstance() {
        if( ! (self::$_instance instanceof self) ) {
        	print_r("init\r\n");
            self::$_instance = new self();
        }
        return self::$_instance;
    }
	
	public function get($name){
		if (array_key_exists($name,$this->config)){
			return $this->config[$name];
		}else{
			return false;
		}
	}
	public function set($name,$value){
		$this->config[$name] = $value;
		$this->ini_array[$name] = $value;
		IniFile::write_ini_file($this->ini_array,FILE_NAME);
	}
	//获取当前路径
	public function getBasePath(){
		$arr = pathinfo(__FILE__);
		return $arr["dirname"];
	}
}

/**
* ini 文件操作。
*/
class IniFile{
	public static function write_ini_file($array,$filename) { 
		$ok   =   ""; 
		$s   =   ""; 
		foreach($array   as   $k=> $v){ 
			if(is_array($v))   { 
				if($k   !=   $ok){ 
					$s   .=   LF. "[$k] ".LF; 
					$ok   =   $k; 
				} 
				$s   .=   write_ini_file($v, " "); 
			}else   { 
				if(trim($v)   !=   $v   ||   strstr($v, "[ ")) 
					$v   =   "\"$v\" "; 
				$s   .=   "$k   =   $v ".LF; 
			} 
		} 
		if($filename   ==   " ") 
			return   $s; 
		else   { 
			$fp   =   fopen($filename, "w"); 
			fwrite($fp,$s); 
			fclose($fp); 
		} 
	}
}

/**
* 计时和内存
* T::BT(1),T::ET(1) 计时
*/
class T{
	
	public static $begin_time = array(); 
	 
	public static function get_microtime() 
    { 
        list($usec, $sec) = explode(' ', microtime()); 
        return ((float)$usec + (float)$sec); 
    } 
    
	public static function BT($i){
		self::$begin_time[$i] -= self::get_microtime();
	}
	public static function ET($i){
		self::$begin_time[$i] += self::get_microtime();
		return self::$begin_time[$i];
	}
	public static function GT($i){
		return self::$begin_time[$i];
	}
	public static function CT($i){
		self::$begin_time[$i] = 0;
	}
	public static function Mem(){
		$mem =  memory_get_peak_usage();
		msg_log("".round($mem/1024/1024,2)."M");
	}
}
//////通用函数///////////////////

function msg_log($msgs,$LF=LF){
	$s = "";
	if(is_array($msgs)){
		foreach($msgs as $m){
			$s.= $m.$LF;
		}
	}else{
		$s.= $msgs.$LF;
	}
	echo $s;
}

function save_file($filename,$msgs,$LF=""){
	$s = "";
	if(is_array($msgs)){
		foreach($msgs as $m){
			$s.= $m.$LF;
		}
	}else{
		$s.= $msgs.$LF;
	}
	$fp = fopen($filename, "w"); 
	fwrite($fp,$s); 
	fclose($fp); 
}

function run_cmd($cmd){
	echo $cmd;
	exec($cmd, $ar, $status);  
	//exec($cmd, $ar, $status); //没显示.可读到显示的值。
	//$rs = system($cmd,$result);//直接显示
	//passthru($cmd);//直接显示
	return array("state"=>$status,
		"logs"=>$ar
	);
}

//var_dump(strtotime("11/Sep/2012:02:06:03 +0800"));
//echo date('Y-m-d H:i:s',strtotime("11/Sep/2012:02:06:03 +0800"));

/**
 * 获取时间
 */
function get_date_time($add=""){
	date_default_timezone_set('PRC');
	if($add==""){
		return date('Y-m-d H:i:s');
	}else{
		return date('Y-m-d H:i:s',$add);
	}
}

/**
 * 比较时间，return d1>=d2
 */
function date_time_deff($d1,$d2){
	if(is_string($d1)) 
	$d1=strtotime($d1); 
	if(is_string($d2)) 
	$d2=strtotime($d2); 
	return   $d1>=$d2;
}
?>